﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Text;
using System.Web.UI;
using System.Xml;
using Common.Utilities;
using Common.Utilities.DLR;
using Workflows.Components.Rules.Properties;

namespace Workflows.Components.Rules
{
    /// <summary>
    /// evaluate condition directly
    /// </summary>
    [Serializable]
    public class DeclarativeRuleCondition : RuleNodeDataBase
    {
        #region member
        private string _FieldName;
        /// <summary></summary>
        public string FieldName
        {
            get
            {
                return this._FieldName;
            }
            set
            {
                this._FieldName = value;
            }
        }

        private SimpleDataType _FieldDataType;
        /// <summary></summary>
        public SimpleDataType FieldDataType
        {
            get
            {
                return this._FieldDataType;
            }
            set
            {
                this._FieldDataType = value;
            }
        }

        private EvaluationOperator _CompareOperator;
        /// <summary></summary>
        public EvaluationOperator CompareOperator
        {
            get
            {
                return this._CompareOperator;
            }
            set
            {
                this._CompareOperator = value;
            }
        }

        private string _CompareAgainst;
        /// <summary></summary>
        public string CompareAgainst
        {
            get
            {
                return this._CompareAgainst;
            }
            set
            {
                this._CompareAgainst = value;
            }
        }
        #endregion

        /// <summary>
        /// 
        /// </summary>
        public DeclarativeRuleCondition()
            : base()
        {
            this.Name = "Condition";
            this.Description = "Condition";
            this.Img = Resources.Search;
            this.RuleNodeType = Rules.RuleNodeType.Conditional;
            
            this._FieldName = string.Empty;
            this._FieldDataType = SimpleDataType.TextType;
            this._CompareAgainst = string.Empty;
            this._CompareOperator = EvaluationOperator.Equals;
            
        }

        public override System.Xml.XmlNode Serialize(ref System.Xml.XmlDocument xDoc, ref System.Xml.XmlNode parentNode)
        {
            XmlNode xNode = base.Serialize(ref xDoc, ref parentNode);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "FieldName",this.FieldName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "FieldDataType",
                                        ((int) this.FieldDataType).ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "Operator", ((int) this.CompareOperator).ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "Against",
                                        SimpleDataTypeUtil.ToDbValue(this.FieldDataType,
                                                                     this.CompareAgainst).ToString());
            return xNode;
        }

        public override RuleNodeDataBase Instantiate(XmlNode xNode)
        {
            DeclarativeRuleCondition declarativeRuleCondition = new DeclarativeRuleCondition();
            declarativeRuleCondition.RuleNodeID=new Guid(xNode.Attributes.GetNamedItem("RuleNodeID").Value);
            declarativeRuleCondition.Name = xNode.Attributes.GetNamedItem("Name").Value;
            declarativeRuleCondition.Description = xNode.Attributes.GetNamedItem("Description").Value;
            declarativeRuleCondition.RuleNodeType = (RuleNodeType) int.Parse(xNode.Attributes.GetNamedItem("RuleNodeType").Value);

            declarativeRuleCondition.FieldName = xNode.Attributes.GetNamedItem("FieldName").Value;
            declarativeRuleCondition.FieldDataType =
                (SimpleDataType) int.Parse(xNode.Attributes.GetNamedItem("FieldDataType").Value);
            declarativeRuleCondition.CompareOperator = (EvaluationOperator) int.Parse(xNode.Attributes.GetNamedItem("Operator").Value);
            declarativeRuleCondition.CompareAgainst = xNode.Attributes.GetNamedItem("Against").Value;
            
            return declarativeRuleCondition;
        }

        public override string DescribeInHtml()
        {
            StringBuilder buffer = new StringBuilder();
            HtmlTextWriter htmlWriter = new HtmlTextWriter(new StringWriter(buffer));
            htmlWriter.RenderBeginTag(HtmlTextWriterTag.Div);
            htmlWriter.RenderBeginTag(HtmlTextWriterTag.B);
            htmlWriter.RenderBeginTag(HtmlTextWriterTag.U);
            htmlWriter.Write(string.Format("Action {0}:", this.RuleNodeID.ToString()));
            htmlWriter.RenderEndTag();
            htmlWriter.RenderEndTag();
            htmlWriter.RenderBeginTag(HtmlTextWriterTag.Br);
            htmlWriter.RenderEndTag();
            htmlWriter.RenderBeginTag(HtmlTextWriterTag.Ul);
            htmlWriter.RenderBeginTag(HtmlTextWriterTag.Li);
            htmlWriter.Write(
                    string.Format("Condition: evaluate {0} using {1} and check result against {2}",
                                  this.FieldName,
                                  this.CompareOperator.ToString(),
                                  this.CompareAgainst == null
                                      ? "null"
                                      : this.CompareAgainst.ToString()));
            htmlWriter.RenderEndTag();
            htmlWriter.RenderEndTag();
            htmlWriter.RenderEndTag();
            return buffer.ToString();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override string Describe()
        {
            StringBuilder buffer=new StringBuilder();
            buffer.Append(string.Format("Action {0}:", this.RuleNodeID.ToString()));
            buffer.Append(Environment.NewLine);
            buffer.Append("Condition: evaluate " +
                              this.FieldName == null
                                  ? "Unknown field name"
                                  : this.FieldName
                                    + " using " +
                                    this.CompareOperator.ToString() + " and check result against " +
                                    this.CompareAgainst == null
                                        ? "Null"
                                        : this.CompareAgainst.ToString());
            
            buffer.Append(Environment.NewLine);
            return buffer.ToString();
        }

        
    }
}
